/*************************************************************************
 *
 * obsluhy handleru prikazu seriove komunikace
 * 
 * (c) Ales Povalac, alpov@alpov.net, http://www.alpov.net/
 * 
 *************************************************************************
 *
 * $Id: serial_hnds.c 65 2006-07-28 07:40:09Z alpov $
 * 
 *************************************************************************/         

#include <string.h>
#include <avr/io.h>
#include "../avrx/avrx.h"
#include "../avrx/AvrXFifo.h"
#include "serial.h"
#include "data.h"
#include "menu.h"


/*************************************************************************
 * obsluha prikazu STDATA_WRITE
 *************************************************************************/ 
void STDATA_W_Handler(PACKET_HEADER *ph, char *data, unsigned char length)
{
    if ((ph->item_hi == ITEM_TEMPERATURE) && (length == sizeof(stdata.temperature))) {
        memcpy(&stdata.temperature, data, sizeof(stdata.temperature));
        AvrXPutFifo(MenuFifo, MENU_REFRESH);
    }
    else if ((ph->item_hi == ITEM_STATE) && (length == 2)) {
        stdata.io_state = *data;
        stdata.reg_state = *(data + 1);
        AvrXPutFifo(MenuFifo, MENU_REFRESH);
    }
    else if ((ph->item_hi == ITEM_ALL) && (length == sizeof(stdata))) {
        memcpy(&stdata, data, sizeof(stdata));
        AvrXPutFifo(MenuFifo, MENU_REFRESH);
    }
    else if ((ph->item_hi == ITEM_MESSAGE) && (length == 1)) {
        MenuMessage(*data);
    }
    else
        return;

    if (ph->dest != ADDR_BROADCAST)
        SerialSendAck(ph);
}


/*************************************************************************
 * obsluha prikazu RWDATA_WRITE
 *************************************************************************/ 
void RWDATA_W_Handler(PACKET_HEADER *ph, char *data, unsigned char length)
{
    void *buffer;
    unsigned char cpy_len;
    
    if (ph->item_hi == ITEM_MODE) {
        buffer = &rwdata.mode;
        cpy_len = sizeof(rwdata.mode);
    }
    else if (ph->item_hi == ITEM_SHIFT) {
        buffer = &rwdata.shift;
        cpy_len = sizeof(rwdata.shift) + sizeof(rwdata.shift_length);
    }
    else if (ph->item_hi == ITEM_SWITCH) {
        buffer = &rwdata.sw_mode;
        cpy_len = sizeof(rwdata.sw_mode) + sizeof(rwdata.sw_datetime);
    }
    else if (ph->item_hi == ITEM_RTC) {
        buffer = &rwdata.now;
        cpy_len = sizeof(rwdata.now);
    }
    else if (ph->item_hi == ITEM_ALL) {
        buffer = &rwdata;
        cpy_len = sizeof(rwdata);
    }
    else
        return;
    
    if (cpy_len != length)
        return;
    
    if (AvrXTestSemaphore(&DataLock) != SEM_DONE)   // nelze-li ziskat mutex, ukoncit bez potvrzeni
        return;

    memcpy(buffer, data, cpy_len);                  // zapsat udaj

    AvrXSetSemaphore(&DataLock);                    // uvolnit mutex

    if (ph->dest != ADDR_BROADCAST)
        SerialSendAck(ph);                          // potvrdit, pokud neni broadcast

    AvrXPutFifo(MenuFifo, MENU_REFRESH);            // obnovit menu
}


/*************************************************************************
 * obsluha prikazu RWDATA_READ
 *************************************************************************/ 
void RWDATA_R_Handler(PACKET_HEADER *ph)
{
    void *buffer;
    unsigned char cpy_len;
    
    if (ph->item_hi == ITEM_MODE) {
        buffer = &rwdata.mode;
        cpy_len = sizeof(rwdata.mode);
    }
    else if (ph->item_hi == ITEM_SHIFT) {
        buffer = &rwdata.shift;
        cpy_len = sizeof(rwdata.shift) + sizeof(rwdata.shift_length);
    }
    else if (ph->item_hi == ITEM_SWITCH) {
        buffer = &rwdata.sw_mode;
        cpy_len = sizeof(rwdata.sw_mode) + sizeof(rwdata.sw_datetime);
    }
    else if (ph->item_hi == ITEM_RTC) {
        buffer = &rwdata.now;
        cpy_len = sizeof(rwdata.now);
    }
    else if (ph->item_hi == ITEM_ALL) {
        buffer = &rwdata;
        cpy_len = sizeof(rwdata);
    }
    else
        return;
    
    ph->dest = ph->src;
    ph->src = ADDR_TERMINAL;
    ph->cmd = CMD_RWDATA_WRITE;
    SerialSendPacket(ph, buffer, cpy_len, 1);
}


/*************************************************************************
 * obsluha prikazu DESC_WRITE
 *************************************************************************/ 
void DESC_W_Handler(PACKET_HEADER *ph, char *data, unsigned char length)
{
    if ((ph->item_hi == ITEM_SENSOR_COUNT) && (length == 1)) {
        AvrXWriteEEProm(&desc.sensor_count, *data);
    }
    else if ((ph->item_hi == ITEM_SENSOR_DESC) && (ph->item_lo < SENSOR_MAX_COUNT) && (length == MAX_DESC_LEN)) {
        WriteEEPromBlock(data, desc.sensor_desc[ph->item_lo], MAX_DESC_LEN);
    }
    else if ((ph->item_hi == ITEM_MODE_COUNT) && (length == 1)) {
        AvrXWriteEEProm(&desc.mode_count, *data);
    }
    else if ((ph->item_hi == ITEM_MODE_DESC) && (ph->item_lo < MODE_MAX_COUNT) && (length == MAX_DESC_LEN)) {
        WriteEEPromBlock(data, desc.mode_desc[ph->item_lo], MAX_DESC_LEN);
    }
    else        
        return;

    if (ph->dest != ADDR_BROADCAST)
        SerialSendAck(ph);

    AvrXPutFifo(MenuFifo, MENU_REFRESH);
}


/*************************************************************************
 * obsluha prikazu DESC_READ
 *************************************************************************/ 
void DESC_R_Handler(PACKET_HEADER *ph)
{
    char buffer[MAX_DESC_LEN];
    unsigned char cpy_len;
    
    if (ph->item_hi == ITEM_SENSOR_COUNT) {
        buffer[0] = AvrXReadEEProm(&desc.sensor_count);
        cpy_len = 1;
    }
    else if ((ph->item_hi == ITEM_SENSOR_DESC) && (ph->item_lo < SENSOR_MAX_COUNT)) {
        ReadEEPromBlock(buffer, desc.sensor_desc[ph->item_lo], sizeof(buffer));
        cpy_len = sizeof(buffer);
    }
    else if (ph->item_hi == ITEM_MODE_COUNT) {
        buffer[0] = AvrXReadEEProm(&desc.mode_count);
        cpy_len = 1;
    }
    else if ((ph->item_hi == ITEM_MODE_DESC) && (ph->item_lo < MODE_MAX_COUNT)) {
        ReadEEPromBlock(buffer, desc.mode_desc[ph->item_lo], sizeof(buffer));
        cpy_len = sizeof(buffer);
    }
    else
        return;

    ph->dest = ph->src;
    ph->src = ADDR_TERMINAL;
    ph->cmd = CMD_DESC_WRITE;
    SerialSendPacket(ph, buffer, cpy_len, 1);
}

